#pragma once

#include <bsp.h>

#if BSP_HAS_USB == 1

// ---- include main.h for hardware supports
#include <main.h>
#include <usbd_def.h>
// ---- else
#include <memory>
#include <signal_os.h>

namespace os {
class USB_CDC_ACM_DEVICE final {
private:
    USBD_HandleTypeDef* m_handle_{};

    explicit USB_CDC_ACM_DEVICE(USBD_HandleTypeDef* handle) : m_handle_(handle) {
    }

public:
    USB_CDC_ACM_DEVICE(USB_CDC_ACM_DEVICE const&) = delete;
    USB_CDC_ACM_DEVICE& operator=(USB_CDC_ACM_DEVICE const&) = delete;

    static USB_CDC_ACM_DEVICE& Instance(USB_TypeDef* usb);

    USBD_HandleTypeDef* GetHandlePtr();

    void RegisterRxCallback(int8_t (*cb)(uint8_t*, uint32_t*));

    Signal<uint8_t*, uint32_t> on_receive{};
    Signal<uint8_t*, uint32_t, uint8_t> tx_complete{};

    USBD_StatusTypeDef Transmit(uint8_t* Buf, uint16_t Len);
};
} // namespace os

#endif